/////////////////////////////////////////////////////////////////////////////
// Original code from libhdfs3. Copyright (c) 2013 - 2014, Pivotal Inc.
// All rights reserved. Author: Zhanwei Wang
/////////////////////////////////////////////////////////////////////////////
//  Modifications by Kumo Inc.
// Copyright (C) Kumo inc. and its affiliates.
// Author: Jeff.li lijippy@163.com
// All rights reserved.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <https://www.gnu.org/licenses/>.
//



#include <kmhdfs/common/write_buffer.h>

#include <google/protobuf/io/coded_stream.h>

using namespace google::protobuf::io;
using google::protobuf::uint8;

namespace Hdfs {
namespace Internal {

#define WRITEBUFFER_INIT_SIZE 64

WriteBuffer::WriteBuffer() :
    size(0), buffer(WRITEBUFFER_INIT_SIZE) {
}

WriteBuffer::~WriteBuffer() {
}

void WriteBuffer::writeVarint32(int32_t value, size_t pos) {
    char buffer[5];
    uint8 * end = CodedOutputStream::WriteVarint32ToArray(value,
                  reinterpret_cast<uint8 *>(buffer));
    write(buffer, reinterpret_cast<char *>(end) - buffer, pos);
}

char * WriteBuffer::alloc(size_t offset, size_t s) {
    assert(offset <= size && size <= buffer.size());

    if (offset > size) {
        return NULL;
    }

    size_t target = offset + s;

    if (target >= buffer.size()) {
        target = target > 2 * buffer.size() ? target : 2 * buffer.size();
        buffer.resize(target);
    }

    size = offset + s;
    return buffer.data() + offset;
}

void WriteBuffer::write(const void * bytes, size_t s, size_t pos) {
    assert(NULL != bytes);
    assert(pos <= size && pos < buffer.size());
    char * p = alloc(size, s);
    memcpy(p, bytes, s);
}

}
}
